import { isUndefined, isNull, PagedList, PageParams, toString } from "mmb";
import * as store_endorse_requestpb from "../grpc-client/service/store_endorse_request_pb";
import { jsTimestampToPb, pbTimestampToJs } from "./helper";
import GrpcErrCode from "../grpc-client/grpcErrCode";
import AuditResult from "../bg-enums/auditResult";
import {
  getBgsStoreEndorseRequestOpSafely,
  getMetadata,
  getOptionsOfLight,
  wrapperGrpcError,
} from "../grpc-client/grpcAdapter";

import {
  StoreEndorseRequest,
  StoreEndorseRequestWithUserInfo,
  ApplyStoreEndorseRequestParams,
  AuditStoreEndorseRequestParams,
} from "./storeDeclareTypes";
/****************************************************************************************/
/*                                   store_endorse_request entity                       */
/****************************************************************************************/

const storeEndorseRequestPbToObject = (
  pb: store_endorse_requestpb.StoreEndorseRequestEntity
): StoreEndorseRequest => {
  return {
    storeEndorseRequestId: toString(pb.getId()),
    storeId: toString(pb.getStoreId()),
    userId: `${pb.getUserId()}`,
    requested: pbTimestampToJs(pb.getRequested())!,
    audited: pbTimestampToJs(pb.getAudited()),
    applyFields: pb.getApplyFields(),
    auditResult: pb.getAuditResult() as AuditResult,
  };
};

/****************************************************************************************/
/*                                   store_endorse_request cmd                          */
/****************************************************************************************/

export const applyStoreEndorseRequest = async ({
  storeId,
  userId,
  applyFields,
}: ApplyStoreEndorseRequestParams): Promise<StoreEndorseRequest> => {
  const cl = getBgsStoreEndorseRequestOpSafely();
  const req = new store_endorse_requestpb.ApplyStoreEndorseRequestRequest();

  req.setStoreId(Number(storeId));
  req.setUserId(Number(userId));
  req.setApplyFields(applyFields);

  return new Promise((resolve, reject) => {
    cl.applyStoreEndorseRequest(
      req,
      getMetadata(),
      getOptionsOfLight(),
      (err, res) => {
        if (!isNull(err)) {
          reject(wrapperGrpcError(err.details));
          return;
        }
        const opRet = res.getOpRet()!;
        if (!opRet.getSuccess()) {
          reject(wrapperGrpcError(opRet.getMsg()));
          return;
        }
        resolve(storeEndorseRequestPbToObject(res.getStoreEndorseRequest()!));
      }
    );
  });
};

export const auditStoreEndorseRequest = async ({
  storeEndorseRequestId,
  audited,
  auditResult,
}: AuditStoreEndorseRequestParams): Promise<StoreEndorseRequest> => {
  const cl = getBgsStoreEndorseRequestOpSafely();
  const req = new store_endorse_requestpb.AuditStoreEndorseRequestRequest();

  req.setId(Number(storeEndorseRequestId));
  req.setAudited(jsTimestampToPb(audited));
  req.setAuditResult(auditResult);

  return new Promise((resolve, reject) => {
    cl.auditStoreEndorseRequest(
      req,
      getMetadata(),
      getOptionsOfLight(),
      (err, res) => {
        if (!isNull(err)) {
          reject(wrapperGrpcError(err.details));
          return;
        }
        const opRet = res.getOpRet()!;
        if (!opRet.getSuccess()) {
          reject(wrapperGrpcError(opRet.getMsg()));
          return;
        }
        resolve(storeEndorseRequestPbToObject(res.getStoreEndorseRequest()!));
      }
    );
  });
};

/****************************************************************************************/
/*                                   store_endorse_request query                        */
/****************************************************************************************/

export const getStoreEndorseRequest = async (
  storeEndorseRequestId: string
): Promise<StoreEndorseRequest> => {
  const cl = getBgsStoreEndorseRequestOpSafely();
  const req = new store_endorse_requestpb.GetStoreEndorseRequestRequest();

  req.setId(Number(storeEndorseRequestId));

  return new Promise((resolve, reject) => {
    cl.getStoreEndorseRequest(
      req,
      getMetadata(),
      getOptionsOfLight(),
      (err, res) => {
        if (!isNull(err)) {
          reject(wrapperGrpcError(err.details));
          return;
        }
        const opRet = res.getOpRet()!;
        if (!opRet.getSuccess()) {
          reject(wrapperGrpcError(opRet.getMsg()));
          return;
        }
        resolve(storeEndorseRequestPbToObject(res.getStoreEndorseRequest()!));
      }
    );
  });
};

export const getStoreEndorseRequestByStoreIDAndUserIDSafely = async (
  storeId: string,
  userId: string
): Promise<StoreEndorseRequest> => {
  const v = await getStoreEndorseRequestByStoreIDAndUserID(storeId, userId);
  return v!;
};

export const getStoreEndorseRequestByStoreIDAndUserID = async (
  storeId: string,
  userId: string
): Promise<StoreEndorseRequest | undefined> => {
  const cl = getBgsStoreEndorseRequestOpSafely();
  const req =
    new store_endorse_requestpb.GetStoreEndorseRequestByStoreIDAndUserIDRequest();

  req.setStoreId(Number(storeId));
  req.setUserId(Number(userId));

  return new Promise((resolve, reject) => {
    cl.getStoreEndorseRequestByStoreIDAndUserID(
      req,
      getMetadata(),
      getOptionsOfLight(),
      (err, res) => {
        if (!isNull(err)) {
          reject(wrapperGrpcError(err.details));
          return;
        }
        const opRet = res.getOpRet()!;
        if (!opRet.getSuccess()) {
          if (opRet.getCode() === GrpcErrCode.NOT_FOUND) {
            resolve(undefined);
            return;
          } else {
            reject(wrapperGrpcError(opRet.getMsg()));
            return;
          }
        }
        resolve(storeEndorseRequestPbToObject(res.getStoreEndorseRequest()!));
      }
    );
  });
};

/****************************************************************************************/
/*                                   store_endorse_requestJoins entity                  */
/****************************************************************************************/

const storeEndorseRequestWithUserInfoPbToObject = (
  pb: store_endorse_requestpb.StoreEndorseRequestWithUserInfoEntity
): StoreEndorseRequestWithUserInfo => {
  return {
    storeEndorseRequestId: toString(pb.getId()),
    storeId: toString(pb.getStoreId()),
    userId: `${pb.getUserId()}`,
    requested: pbTimestampToJs(pb.getRequested())!,
    audited: pbTimestampToJs(pb.getAudited()),
    applyFields: pb.getApplyFields(),
    auditResult: pb.getAuditResult() as AuditResult,
    userPic: pb.getUserPic(),
  };
};

/****************************************************************************************/
/*                                   store_endorse_requestJoins query                   */
/****************************************************************************************/

export const listStoreEndorseRequestWithUserInfosByStoreID = async (
  storeId: string,
  isWaitAudit: boolean,
  pager: PageParams
): Promise<PagedList<StoreEndorseRequest>> => {
  const cl = getBgsStoreEndorseRequestOpSafely();
  const req =
    new store_endorse_requestpb.ListStoreEndorseRequestWithUserInfosByStoreIDRequest();

  req.setLimit(pager.limit);
  req.setOffset(pager.offset);
  req.setTs(jsTimestampToPb(pager.ts));
  req.setStoreId(Number(storeId));
  let auditResults = isWaitAudit
    ? [AuditResult.PENDING]
    : [AuditResult.APPROVED, AuditResult.REJECTED];
  req.setAuditResultsList(auditResults);

  return new Promise((resolve, reject) => {
    cl.listStoreEndorseRequestWithUserInfosByStoreID(
      req,
      getMetadata(),
      getOptionsOfLight(),
      (err, res) => {
        if (!isNull(err)) {
          reject(wrapperGrpcError(err.details));
          return;
        }
        const opRet = res.getOpRet()!;
        if (!opRet.getSuccess()) {
          reject(wrapperGrpcError(opRet.getMsg()));
          return;
        }
        const ret: PagedList<StoreEndorseRequest> = {
          total: 0,
          items: [],
        };
        ret.total = res.getTotal();
        ret.items = res
          .getStoreEndorseRequestWithUserInfosList()
          .map(storeEndorseRequestWithUserInfoPbToObject);
        resolve(ret);
      }
    );
  });
};
